package cn.edu.scau.util;

import cn.edu.scau.config.Audience;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import java.security.Key;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;


/**
 * JWT工具类（抽象类,无需实例化生成）：生成Token，验证Token
 *
 */
public abstract class JWTTokenUtil {
    public static final String AUTH_HEAD_KEY="Authorization";

    public static String createJWT(String userid, String username, Audience audience){
        //使用SHMAC,SHA-256加密算法
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
        //获取当前时间
        long begin_millis = System.currentTimeMillis();
        Date begin_date = new Date(begin_millis);
        //生成签名密钥
        byte[] api = DatatypeConverter.parseBase64Binary(audience.getBase64Secret());
        Key key = new SecretKeySpec(api,signatureAlgorithm.getJcaName());
        //设置JWT的header（头部信息）

        Map<String,Object> header = new HashMap<String,Object>();
        header.put("alg", SignatureAlgorithm.HS256.getValue());
        header.put("typ","JWT");
        //设置JWT的payload(有效载荷)
        JwtBuilder builder = Jwts.builder().setHeader(header)
                                    .claim("userid",userid)//将特定的用户信息存储在claim中，敏感数据需要加密
                                    .setSubject(username)//设置JWT主体body
                                    .setIssuer(audience.getClientid())
                                    .setIssuedAt(new Date())
                                    .setAudience(audience.getName())
                                    .signWith(signatureAlgorithm,key);
        //添加过期时间
        int time = audience.getExpiresSecond();
        if(time>0){
            long exp = begin_millis+time*1000;
            Date exp_date = new Date(exp);
            builder.setExpiration(exp_date)//是一个时间戳，exp_date代表是过期时间
                    .setNotBefore(begin_date);//是一个时间戳,bigin_date开始生效时间，在此之前验证都是失败
        }
        return builder.compact(); //生成序列化安全url字符串
    }

    /**
     * 解析JWT
     * @param token
     * @param base64Security
     * @return
     */
    public static Claims parseJWT(String token, String base64Security){
            Claims claims = Jwts.parser()
                    .setSigningKey(DatatypeConverter.parseBase64Binary(base64Security))
                    .parseClaimsJws(token)
                    .getBody();
            return claims;
    }
/**
 *从token中获取username
 */
    public static String getUserName(String token,String base64Security){
        return parseJWT(token, base64Security).getSubject();
    }
    /**
     *从token中获取userid
     */
    public static String getUserId(String token,String base64Security){
        return parseJWT(token, base64Security).get("userid",String.class);
    }

    /**
     * 判断客户端的JWT是否过期
     * @param token
     * @param base64Security
     * @return
     */
    public static boolean isExpiration(String token,String base64Security){
        return parseJWT(token, base64Security).getExpiration().before(new Date());
    }
}
